# 修改配置相关接口
from flask import Blueprint, request,session
import configparser
import os, json, bcrypt
import yaml
import re
from Logger import logger
from utils import get_dir, get_global_config, handle_exception, handle_success, get_local_ip
from db_handler import db_handler

setting = Blueprint('setting', __name__)


# 获取项目清单
@setting.route('/file/getProjectList', methods=['POST'])
def get_project_list():
    try:
        # # root_path = get_global_config()['rootPath']
        # # if not os.path.exists(root_path):
        # #     return handle_exception("根路径错误", "全局配置错误，请联系管理员进行配置")
        # #
        # # dir_list = get_dir(root_path)  # 获取根路径下所有文件夹名
        # # project_list = [dir_name for dir_name in dir_list if dir_name != 'uploadFile']
        # if 'userid' not in session or 'loginname' not in session:
        #     return handle_exception("会话失效", "会话失效，请重新登录")
        # user_id = session['userid']
        # user_name = session['loginname']
        # # 查询用户信息以获取是否为管理员
        # query = "SELECT is_admin FROM User WHERE id = %s"
        # user_info = db_handler.execute_query(query, (user_id,))
        #
        # if not user_info:
        #     return handle_exception("用户信息获取失败", "用户信息获取失败")
        #
        # is_admin = user_info[0]['is_admin']
        #
        # if is_admin:
        #     query = "SELECT project_name FROM project"
        #     project_list = db_handler.execute_query(query)
        # else:
        #     query = "SELECT project_name FROM project where user_id= %s"
        #     project_list = db_handler.execute_query(query, (user_id,))
        # # project_list = db_handler.execute_query(query,(user_id,))
        #
        # # 处理查询结果，将每个项目名称添加到列表中
        # if project_list is not None:
        #     project_names = [project['project_name'] for project in project_list]
        # else:
        #     project_names = []

        logger.info("当前会话内容: %s", session)
        # 从会话中获取项目列表
        project_names = session.get('projects', None)
        if project_names is None:
            return handle_exception("会话失效", "会话失效，请重新登录")
        logger.info("project FilName list：%s", project_names)
    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success(project_names, "success")


# 获取邮件配置
@setting.route('/file/getEmailConfig', methods=['POST'])
def get_email_config():
    try:
        params = request.json
        print("params：%s", params)
        root_path = get_global_config()['rootPath']
        if not os.path.exists(root_path):
            return handle_exception("根路径错误", "全局配置错误，请联系管理员进行配置")
        if not params.get('projectName'):
            return handle_exception("err", "还未创建项目")
        path = os.path.join(root_path, params["projectName"], 'config','config.ini')
        if not os.path.isfile(path):
            return handle_exception("error", "不存在邮件配置文件")
        data = {}
        # 读取
        cf = configparser.ConfigParser()
        cf.read(path, 'utf-8')
        secs = cf.sections()  # 获得所有区域
        for sec in secs:
            data[sec] = {}
            items = cf.items(sec)  # 获取区域键值对
            for item in items:
                # 如果字段名是 'password'，则对其进行加密处理
                if sec == 'EmailInfo' and item[0] == 'password' and item[1]:
                    # 使用 bcrypt 加密密码
                    hashed_password = bcrypt.hashpw(item[1].encode('utf-8'), bcrypt.gensalt())
                    data[sec][item[0]] = hashed_password.decode('utf-8')  # 将字节转换为字符串
                else:
                    data[sec][item[0]] = item[1]
            logger.info("email file data is：%s", data)
    except Exception as err:  # 捕获异常
        return handle_exception(err, "程序异常")
    else:
        return handle_success(data, "success")


# 保存邮件
@setting.route('/file/saveEmailConfig', methods=['POST'])
def save_email_config():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        logger.info("params：%s", params)
        path = os.path.join(root_path, params["projectName"], 'config','config.ini')
        data = params["data"]
        local_ip = get_local_ip()
        report_path = os.path.join(root_path, params["projectName"], "report", "TestReport.html")
        report_url = "http://" + local_ip + "/getReport/" + params["projectName"] + "/report"
        data["TestInfo"]["fullreport"] = report_url

        logger.info(data)
        if os.path.isfile(path):
            cf = configparser.ConfigParser()
            cf.read(path, 'utf-8')
            secs = cf.sections()  # 获得所有区域
            for sce in secs:
                opts = cf.options(sce)  # 获取区域的所有key
                for opt in opts:
                    print(sce, opt, data[sce][opt])
                    cf.set(sce, opt, data[sce][opt])  # 修改
            cf.write(open(path, "w", encoding="utf-8"))  # 写入
        else:
            cf = configparser.ConfigParser()
            secs = data.keys()  # 获得所有区域
            for sce in secs:
                cf.add_section(sce)  # 添加section
                opts = data[sce].keys()  # 获取区域的所有key
                for opt in opts:
                    cf.set(sce, opt, data[sce][opt])  # 修改
            cf.write(open(path, "w", encoding="utf-8"))  # 写入

    except Exception as err:  # 捕获异常
        return handle_exception(err, "程序异常")
    else:
        return handle_success(request.json, "success")


# # 保存YAML配置
# @setting.route('/file/saveYamlConfig', methods=['POST'])
# def save_yaml_config():
#     try:
#         params = request.json
#         root_path = get_global_config()['rootPath']
#         project_dir = os.path.join(root_path, params["projectName"])
#         path = os.path.join(project_dir, params["projectName"] + '.yaml')
#         data = params["data"]
#         logger.info("modify yaml file data is：%s", data)
#         with open(path, 'r', encoding='utf-8') as f:
#             old_yaml = yaml.load(f, Loader=yaml.FullLoader)
#
#         old_yaml['settings']['env']['Runtime'] = data['settings']['env']['Runtime']  # 修改runtime
#         old_yaml['execution'] = []  # 清空 old_yaml['execution'] 列表
#         for item in data['execution']:
#             # 将'ramp-up'值加上时间单位's'
#             item['ramp-up'] = f"{item['ramp-up']}s"
#             old_yaml['execution'].append(item)  # 添加execution
#
#         with open(path, 'w', encoding='utf-8') as f:
#             yaml.dump(data=old_yaml, stream=f, allow_unicode=True)  # yaml.dump()函数，就是将yaml文件一次性全部写入你创建的文件
#
#     except Exception as err:  # 捕获异常
#         return handle_exception(err, "程序异常")
#     else:
#         return handle_success(request.json, "success")


# 快速修改执行策略
# 测试配置页面-测试策略-快速修改
# 参数：
"""
{
    "projectName":"test0516",
    "data":{"concurrency":1,"targettime":1,"ramp-up":"1s"}
}"""


# 返回：request.json
@setting.route('/file/overallUpdateYamlConfig', methods=['POST'])
def overall_update_yaml_config():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        data = params["data"]
        logger.info("modify yaml file data is：%s", data)
        if (params["projectName"]!=""):
            with open(path, 'r', encoding='utf-8') as f:
                old_yaml = yaml.load(f, Loader=yaml.FullLoader)

            for item in old_yaml['execution']:
                item['concurrency'] = data['concurrency']
                item['targettime'] = data['targettime']
                item['ramp-up'] = data['ramp-up']
                # 将 'ramp-up' 值加上时间单位 's'
                item['ramp-up'] = f"{data['ramp-up']}s"

            with open(path, 'w', encoding='utf-8') as f:
                yaml.dump(data=old_yaml, stream=f, allow_unicode=True)
        else:
            return handle_exception("请先选择项目", "请先选择项目")
    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success(request.json, "success")


# 获取yaml的runntime
# 传参： "projectName":"yueer"
# 返回： {
#         "runtime": 500
#     }
@setting.route('/file/getYamlRuntime', methods=['POST'])
def get_yaml_runtime():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        print("params:", params)
        if not os.path.exists(root_path):
            return handle_exception("根路径错误", "全局配置错误，请联系管理员进行配置")
        if not params.get('projectName'):
            return handle_exception("error", "还未创建项目")
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        if not os.path.isfile(path):
            return handle_exception("error", "yaml文件不存在")
        with open(path, 'r', encoding='utf-8') as file:
            data = yaml.safe_load(file)

            runtime = data['settings']['env']['Runtime']

            logger.info("yaml runtime is: %s", runtime)
    except Exception as err:  # 捕获异常
        return handle_exception(err, "程序异常")
    else:
        return handle_success({'runtime': runtime}, "success")


# 获取yaml的excution
# 传参： {
#     "projectName":"yueer",
#     "pageNum":2,
#     "pageSize":10,
#     "sencrioName":""
# }
# 返回：data": {
#         "list": [
#             {
#                 "concurrency": 100,
#                 "ramp-up": 10,
#                 "scenario": "TC02_打开单据",
#                 "targettime": 5000
#             }
#         ],
#         "total": 1
#     },
@setting.route('/file/getYamlExecution', methods=['POST'])
def get_yaml_execution():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        print("params:", params)
        if not os.path.exists(root_path):
            return handle_exception("根路径错误", "全局配置错误，请联系管理员进行配置")
        if not params.get('projectName'):
            return handle_exception("error", "还未创建项目")
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        if not os.path.isfile(path):
            return handle_exception("error", "yaml文件不存在")
        with open(path, 'r', encoding='utf-8') as file:
            data = yaml.safe_load(file)

            execution_values = data.get('execution', [])
            total_items = len(execution_values)

            sencrio_name = params.get('sencrioName')  # 获取前端传回的sencrioName参数

            result = {
                'list': []
            }
            if execution_values:
                for execution in execution_values:
                    concurrency = execution['concurrency']
                    ramp_up = execution['ramp-up']
                    ramp_up_value = int(re.search(r'\d+', ramp_up).group())
                    scenario = execution['scenario']
                    targettime = execution['targettime']

                    if sencrio_name and sencrio_name.lower() not in scenario.lower():
                        continue  # 如果sencrio_name存在且不在scenario中，则跳过当前数据

                    result['list'].append({
                        'scenario': scenario,
                        'concurrency': concurrency,
                        'ramp-up': ramp_up_value,
                        'targettime': targettime
                    })

            # 根据sencrio_name是否为空，决定是进行模糝搜索还是按页展示数据
            if not sencrio_name:  # 如果sencrio_name为空，按页展示数据
                page_num = params.get('pageNum', 1)
                page_size = params.get('pageSize', 10)
                start_index = (page_num - 1) * page_size
                end_index = min(start_index + page_size, total_items)

                response_data = {
                    'list': result['list'][start_index:end_index],
                    'total': len(result['list'])
                }
            else:  # 如果sencrio_name不为空，先进行模糝搜索，再根据页号展示数据
                response_data = {
                    'list': result['list'],
                    'total': len(result['list'])
                }

            logger.info("yaml execution is: %s", response_data)
    except Exception as err:  # 捕获异常
        return handle_exception(err, "程序异常")
    else:
        return handle_success(response_data, "success")


# 添加测试场景
# 传参：{
#     "projectName":"test01",
#     "scenarioName":["TC09_系统登录","TC10TEST"]
# }

@setting.route('/file/addScenario', methods=['POST'])
def add_scenario():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        scenarios_name = params["scenarioName"]

        with open(path, 'r', encoding='utf-8') as file:
            data = yaml.safe_load(file)

        for new_scenario_name in scenarios_name:
            new_execution = {
                'concurrency': 100,
                'distributed': [],
                'hold-for': '${Runtime}s',
                'lastavgtime': 0,
                'lasttps': 0,
                'ramp-up': '10s',
                'scenario': new_scenario_name,
                'targettime': 5000
            }
            data['execution'].append(new_execution)

            if new_scenario_name not in data['scenarios']:
                new_script_path = f"${{testplans_DIR}}/{new_scenario_name}.jmx"
                data['scenarios'][new_scenario_name] = {
                    'modifications': {
                        'disable': ["Res_Memory", "Res_CPU"],
                        'set-prop': {
                            'Errors Writer>filename': f"${{Jtl_DIR}}/{new_scenario_name}_error.jtl",
                            'KPI Writer>filename': f"${{Jtl_DIR}}/{new_scenario_name}_kpi.jtl",
                            'Res_CPU>filename': f"${{Jtl_DIR}}/{new_scenario_name}_cpu.jtl",
                            'Res_Memory>filename': f"${{Jtl_DIR}}/{new_scenario_name}_memory.jtl",
                            'Runtime Controller>RunTime.seconds': "${Runtime}"
                        }
                    },
                    'script': new_script_path
                }

        with open(path, 'w', encoding='utf-8') as file:
            yaml.dump(data, file, allow_unicode=True)

    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success("success", "添加场景成功")


# 删除测试场景
# 传参：{
#     "projectName":"test01",
#     "scenarioName":["TC09_系统登录","TC10TEST"]
# }

@setting.route('/file/deleteScenario', methods=['POST'])
def delete_scenario():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        scenarios_name = params["scenarioName"]

        with open(path, 'r', encoding='utf-8') as file:
            data = yaml.safe_load(file)

        # 遍历场景名称列表
        for scenario_name in scenarios_name:
            execution_to_delete = None
            for execution in data['execution']:
                if execution['scenario'] == scenario_name:
                    execution_to_delete = execution
                    break

            # scenario_to_delete = data['scenarios'].get(scenario_name)

            if execution_to_delete:
                data['execution'].remove(execution_to_delete)

            # if scenario_to_delete:
            #     del data['scenarios'][scenario_name]

        with open(path, 'w', encoding='utf-8') as file:
            yaml.dump(data, file, allow_unicode=True)

    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success("success", "删除场景成功")


# 修改场景策略
# 执行页-编辑按钮
# 参数：
"""
{
    "projectName":"test0516",
    "data":{"scenario":"TC01_登录", "concurrency":1,"targettime":1,"ramp-up":"1s"}
}"""


@setting.route('/file/updateScenario', methods=['POST'])
def update_scenario():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        data = params["data"]
        scenario_name = params["data"]["scenario"]

        with open(path, 'r', encoding='utf-8') as f:
            old_yaml = yaml.load(f, Loader=yaml.FullLoader)

        for item in old_yaml['execution']:
            if item['scenario'] == scenario_name:
                item['concurrency'] = params["data"]["concurrency"]
                item['ramp-up'] = params["data"]["ramp-up"]
                item['targettime'] = params["data"]["targettime"]
                # 将 'ramp-up' 值加上时间单位 's'
                item['ramp-up'] = f"{data['ramp-up']}s"
                break

        with open(path, 'w', encoding='utf-8') as f:
            yaml.dump(data=old_yaml, stream=f, allow_unicode=True)
    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success(request.json, "success")


# 修改执行时间
# 前端传参：
"""
{
    "projectName":"yueer",
    "runntime":1000
}
"""


@setting.route('/file/updateTime', methods=['POST'])
def update_time():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        path = os.path.join(project_dir, params["projectName"] + '.yaml')
        new_runtime = params["data"]["Runtime"]

        with open(path, 'r', encoding='utf-8') as f:
            yaml_data = yaml.load(f, Loader=yaml.FullLoader)

        # 修改yaml中的Runtime字段为新的时间值
        yaml_data['settings']['env']['Runtime'] = new_runtime

        with open(path, 'w', encoding='utf-8') as f:
            yaml.dump(data=yaml_data, stream=f, allow_unicode=True)
    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success(request.json, "success")
